import * as vscode from 'vscode';
import {ProgressLocation, TextDocument, Uri, WebviewPanelOnDidChangeViewStateEvent} from 'vscode';
import * as path from 'path';
import * as fs from 'fs';

class LayoutPanel implements vscode.CustomTextEditorProvider {
    static _instance: LayoutPanel | undefined;
    public static viewType: string = 'lvgl-layout';
    private _context: vscode.ExtensionContext;
    private _indexFilePath: string = 'out/dist/index.html';
    private _webviewPanel: vscode.WebviewPanel | undefined;
    private _document: TextDocument | undefined;
    private _hideProgress: boolean = false;
    private _activeUri: Uri | undefined;
    static mPort: number = 0;

    public static register(port: number, context: vscode.ExtensionContext): vscode.Disposable {
        console.log("register");
        this.mPort = port;
        //注册自定义编辑器
        this._instance = new LayoutPanel(context);
        let option = {
            webviewOptions: {
                retainContextWhenHidden: true
            }
        }
        const providerRegistration = vscode.window.registerCustomEditorProvider(LayoutPanel.viewType, this._instance, option);
        return providerRegistration;
    }

    public static getInstance() {
        return this._instance;
    }

    constructor(context: vscode.ExtensionContext) {
        this._context = context;
    }

    public async resolveCustomTextEditor(document: vscode.TextDocument, webviewPanel: vscode.WebviewPanel, token: vscode.CancellationToken): Promise<void> {
        console.log("resolveCustomTextEditor");
        this.showProgress();
        let htmlPath = path.join(this._context.extensionPath, this._indexFilePath);

        webviewPanel.webview.options = {
            enableScripts: true,
            localResourceRoots: [vscode.Uri.file(path.dirname(htmlPath))],
        };

        webviewPanel.webview.html = this.getHtmlForWebview(webviewPanel.webview);

        this.hideProgress();
        this._document = document
        this._webviewPanel = webviewPanel
        this._activeUri = document.uri;

        // for switch panel, current document uri update fail.
        // vscode.window.activeTextEditor will return undefined, because a custom editor is not a TextEditor.
        const changeViewStateSub = webviewPanel.onDidChangeViewState((event: WebviewPanelOnDidChangeViewStateEvent) => {
            if (event.webviewPanel.active) {
                this._activeUri = document.uri;
            }
        });

        webviewPanel.onDidDispose(e => {
            changeViewStateSub.dispose();
        });
    }

    public getHtmlForWebview(webview: vscode.Webview): string {
        let url = `http://localhost:${LayoutPanel.mPort}/index1.html`;
        return `<!DOCTYPE html>
                <html lang="en">
                <body style="padding: 0">
                <div style="height: 100vh; width: 100%">
                    <iframe sandbox="allow-forms allow-pointer-lock allow-same-origin allow-popups allow-scripts allow-top-navigation" id="mIframe" style="width: 100%;height: 100%" src="${url}" frameborder="0"></iframe>
                </div>
                </body>
                </html>`;
    }

    public updateLayoutDocument(json: string, document: vscode.TextDocument | undefined) {
        const edit = new vscode.WorkspaceEdit();
        let uri = document?.uri;
        if (!uri) {
            console.error("update layout document fail, uri invalid, uri:", uri);
            return;
        }
        let oldContent = document?.getText();
        let newContent = json;
        if (oldContent === newContent) {
            return;
        }

        edit.replace(uri,
            new vscode.Range(0, 0, 1, 0),
            json);

        return vscode.workspace.applyEdit(edit);
    }

    public static getLayoutDocument() {
        return this._instance?._document
    }

    public getActiveUri(): Uri | undefined {
        return this._activeUri;
    }

    public updateActiveUri(uri: Uri) {
        this._activeUri = uri;
    }

    public showProgress() {
        this._hideProgress = false
        vscode.window.withProgress({
            location: ProgressLocation.Notification,
            title: "加载中...",
        }, (progress, token) => {
            const p = new Promise<void>(resolve => {
                let timer = setInterval(() => {
                    if (this._hideProgress) {
                        resolve();
                        clearInterval(timer)
                    }
                }, 1000);
            });
            return p
        })
    }

    public hideProgress() {
        this._hideProgress = true
    }
}

export { LayoutPanel }
